﻿/*******************************************************
 * 
 * 作者：胡庆访
 * 创建时间：20130326 16:08
 * 说明：此文件只包含一个类，具体内容见类型注释。
 * 运行环境：.NET 4.0
 * 版本号：1.0.0
 * 
 * 历史记录：
 * 创建文件 胡庆访 20130326 16:08
 * 
*******************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Office.Interop.Word;
using Word = Microsoft.Office.Interop.Word;

namespace MSDNConverter
{
    public class WordWriter
    {
        private static Object oTrue = true;

        private static Object oFalse = false;

        private Application _word;

        private Document _doc;

        public Article Article { get; set; }

        private int _totalCount;
        private int _currentIndex;

        public void Write()
        {
            try
            {
                //Start Word and create a new document.
                this._word = new Word.Application();
                this._word.Visible = true;
                this._doc = _word.Documents.Add();
            }
            catch (COMException)
            {
                Console.WriteLine("error occured in writing to word, you must have word2010 installed!");
            }

            this._currentIndex = 0;
            this._totalCount = this.Article.CountAll();

            this.WriteArticleTree(this.Article);

            this.AddTableOfContents();
        }

        private void WriteArticleTree(Article item)
        {
            this.WriteSingleArticle(item);

            //children
            foreach (var child in item.Children)
            {
                this.WriteArticleTree(child);
            }
        }

        private void WriteSingleArticle(Article item)
        {
            Console.WriteLine(string.Format("write content of '{0}' to Word.({1}/{2})", item.Raw.Title, this._currentIndex++, this._totalCount));

            //标题
            var titleParagraph = _doc.Content.Paragraphs.Add();
            var titleRange = titleParagraph.Range;
            titleRange.Text = item.FullTitle;
            titleRange.Font.Bold = 1;
            titleRange.Font.Size = 20;
            var level = item.Raw.Level - 1;
            if (level > 0)
            {
                titleParagraph.Format.OutlineLevel = (WdOutlineLevel)level;
            }
            titleParagraph.Format.SpaceBefore = 24;    //24 pt spacing after paragraph.
            titleRange.InsertParagraphAfter();

            //内容
            bool isCode = false;
            foreach (var paragraph in item.Paragraphs)
            {
                var contentParagraph = _doc.Content.Paragraphs.Add();
                var contentRange = contentParagraph.Range;
                var contentFormat = contentParagraph.Format;

                if (paragraph.IsImage)
                {
                    contentRange.InlineShapes.AddPicture(paragraph.Content);
                }
                else
                {
                    contentRange.Text = paragraph.Content;
                    if (paragraph.IsSubTitle)
                    {
                        contentRange.Font.Bold = 1;
                        contentRange.Font.Size = 16;
                    }

                    if (paragraph.IsCodeStart)
                    {
                        isCode = true;
                        contentFormat.SpaceBefore = 12;
                    }
                    else
                    {
                        //代码行，不需要间隙；其它行，间隙为 6.
                        contentFormat.SpaceBefore = isCode ? 0 : 6;
                    }
                    if (paragraph.IsCodeEnd)
                    {
                        isCode = false;
                        contentFormat.SpaceAfter = 12;
                    }
                    else
                    {
                        contentFormat.SpaceAfter = 0;
                    }
                }
                contentFormat.OutlineLevel = WdOutlineLevel.wdOutlineLevelBodyText;
                contentRange.InsertParagraphAfter();
            }
        }

        /// <summary>
        /// 添加目录。
        /// </summary>
        /// <param name="doc"></param>
        private void AddTableOfContents()
        {
            object x = 0;
            var range = this._doc.Range(ref x, ref x);
            Object oUpperHeadingLevel = 1;
            Object oLowerHeadingLevel = 9;
            Object oTOCTableID = "TableOfContents";
            var oMissing = Type.Missing;
            this._doc.TablesOfContents.Add(range, ref oTrue, ref oUpperHeadingLevel,
                ref oLowerHeadingLevel, ref oMissing, ref oTOCTableID, ref oTrue,
                ref oTrue, ref oMissing, ref oTrue, ref oTrue, ref oTrue);
        }
    }
}